<script setup lang="ts">
import { computed, defineProps, defineExpose, reactive, ref, watch } from 'vue'
import { omit } from 'lodash-es'
import { FormInstance } from 'element-plus'

interface FormMakerItemRender extends FormMakerItem {
  formItemProps: Record<string, any>
}

const props = defineProps({
  name: { type: String, required: true },
  disabled: { type: [Boolean, Function] },
  model: { type: Object, default: () => reactive({}) },
  options: { type: Array as PropType<FormMakerItem[]>, required: true },
})

const withOptionDefaults = (options: FormMakerItem[]) => {
  return options.map(opt => {
    return {
      ...opt,
      component: opt.component || {
        key: 'ElInput',
        props: {
          placeholder: '请输入' + opt.label
        }
      },
      formItemProps: {
        label: opt.label,
        prop: opt.field
      }
    } as FormMakerItemRender
  })
}
const options = ref<FormMakerItemRender[]>();
watch(props.options, () => {
  options.value = withOptionDefaults(props.options)
}, { immediate: true })


const rules = computed(() => {
  const formRules = {}
  options.value.forEach(opt => {
    const optRules = []
    if (opt.required) {

      optRules.push({
        required: true,
        message: opt.label + "不能为空",
        trigger: 'blur',
      })
    }

    formRules[opt.field] = optRules
  })
  return formRules;
})

const model = ref({})

watch(props.model, (_model: object) => {
  if (_model) {
    model.value = _model
  }
}, { immediate: true })

const formRef = ref<FormInstance>();
const formProps = computed(() => ({
  inline: true,
  labelPosition: 'right',
  labelWidth: 85,
  disabled: typeof props.disabled === 'function' ? props.disabled() : props.disabled,
  // validateOnRuleChange: false,
  ...omit(props, ['options', 'name', 'model', 'disabled'])
}));

const handChange = (opt: FormMakerItemRender) => {

}

defineExpose<FormMakerInstance>({
  setData: (input: any) => {
    model.value = input
  },
  validate: () => {
    return new Promise((reslove, reject) => {
      formRef.value.validate((isValid) => {
        if (isValid) {
          reslove()
        } else {
          reject()
        }

      })
    })
  }
})

</script>


<template>
  <el-form :model="model" v-bind="formProps" :rules="rules" ref="formRef">
    <slot name="default"></slot>
    <el-form-item v-for="opt of options" :key="opt.field" v-bind="opt.formItemProps">
      <ComponentRender v-model="model[opt.field]" :render="opt.component" @change="handChange(opt)" />
    </el-form-item>
    <slot name="append"></slot>
  </el-form>
</template>